﻿[XmlRoot(ElementName = "author", Namespace = "")]
public class Author
{
    string first;
    [XmlElement(ElementName = "first")]
    public string FirstName
    {
        set { first = value; }
        get { return first; }
    }

    string last;
    [XmlElement(ElementName = "last")]
    public string LastName
    {
        set { last = value; }
        get { return last; }
    }
}
[XmlRoot(ElementName = "book", Namespace = "")]
public class Book
{
    string title;
    [XmlElement(ElementName = "title")]
    public string Title
    {
        set { title = value; }
        get { return title; }
    }

    Author author;
    [XmlElement(ElementName = "author",Type=typeof(Author))]
    public Author Author
    {
        set { author = value; }
        get { return author; }
    }

    string publisher;
    [XmlElement(ElementName = "publisher")]
    public string Publisher
    {
        set { publisher = value; }
        get { return publisher; }
    }

    double price;
    [XmlElement(ElementName = "price", Type = typeof(double))]
    public double Price
    {
        set { price = value; }
        get { return price; }
    }

    int year;
    [XmlAttribute("year")]
    public int Year
    {
        set { year = value; }
        get { return year; }
    }

    public static implicit operator Book(string xml)
    {
        return xml.GetInstance<Book>();
    }
}
//定义2个帮助类
 /// <summary>
    /// 通过反射访问属性（Attribute）信息的工具类
    /// </summary>
    public static class AttributeHelper
    {
        /// <summary>
        /// 获取某个类型包括指定属性的集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IList<T> GetCustomAttributes<T>(Type type) where T : Attribute
        {
            if (type == null) throw new ArgumentNullException("type");
            T[] attributes = (T[])(type.GetCustomAttributes(typeof(T), false));
            return (attributes.Length == 0) ? null : new List<T>(attributes);
        }

        /// <summary>
        /// 获得某各类型包括指定属性的所有方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IList<MethodInfo> GetMethodsWithCustomAttribute<T>(Type type) where T : Attribute
        {
            if (type == null) throw new ArgumentNullException("type");
            MethodInfo[] methods = type.GetMethods();
            if ((methods == null) || (methods.Length == 0)) return null;
            IList<MethodInfo> result = new List<MethodInfo>();
            foreach (MethodInfo method in methods)
                if (method.IsDefined(typeof(T), false))
                    result.Add(method);
            return result.Count == 0 ? null : result;
        }

        /// <summary>
        /// 获取某个方法指定类型属性的集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="method"></param>
        /// <returns></returns>
        public static IList<T> GetMethodCustomAttributes<T>(MethodInfo method) where T : Attribute
        {
            if (method == null) throw new ArgumentNullException("method");
            T[] attributes = (T[])(method.GetCustomAttributes(typeof(T), false));
            return (attributes.Length == 0) ? null : new List<T>(attributes);
        }
      
        /// <summary>
        /// 获取某个方法指定类型的属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="method"></param>
        /// <returns></returns>
        public static T GetMethodCustomAttribute<T>(MethodInfo method) where T : Attribute
        {
            IList<T> attributes = GetMethodCustomAttributes<T>(method);
            return (attributes == null) ? null : attributes[0];
        }

        /// <summary>
        /// 获得某各类型包括指定属性的所有属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IList<PropertyInfo> GetPropertyWithCustomAttribute<T>(Type type) where T : Attribute
        {
            if (type == null) throw new ArgumentNullException("type");
            PropertyInfo[] propes = type.GetProperties();
            if ((propes == null) || (propes.Length == 0)) return null;
            IList<PropertyInfo> result = new List<PropertyInfo>();
            foreach (PropertyInfo p in propes)
                if (p.IsDefined(typeof(T), false))
                    result.Add(p);
            return result.Count == 0 ? null : result;
        }

        /// <summary>
        /// 获取某个属性指定类型属性的集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="method"></param>
        /// <returns></returns>
        public static IList<T> GetPropertyCustomAttributes<T>(PropertyInfo property) where T : Attribute
        {
            if (property == null) throw new ArgumentNullException("method");
            T[] attributes = (T[])(property.GetCustomAttributes(typeof(T), false));
            return (attributes.Length == 0) ? null : new List<T>(attributes);
        }
        /// <summary>
        /// 获取某个属性指定类型的属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="method"></param>
        /// <returns></returns>
        public static T GetPropertyCustomAttribute<T>(PropertyInfo property) where T : Attribute
        {
            IList<T> attributes = GetPropertyCustomAttributes<T>(property);
            return (attributes == null) ? null : attributes[0];
        }
    }


public static class ExtendClass
{
    static List<Type> types;
    static ExtendClass()
    {
        types = new List<Type>();
        types.Add(typeof(byte));
        types.Add(typeof(short));
        types.Add(typeof(int));
        types.Add(typeof(long));
        types.Add(typeof(sbyte));
        types.Add(typeof(ushort));
        types.Add(typeof(uint));
        types.Add(typeof(ulong));
        types.Add(typeof(float));
        types.Add(typeof(double));
        types.Add(typeof(decimal));
        types.Add(typeof(char));
        types.Add(typeof(string));
        types.Add(typeof(Enum));
    }

    public static T GetInstance<T>(this string xml) where T : class
    {
        XmlTextReader xmlReader = new XmlTextReader(new StringReader(xml));
        XmlSerializer serializer = new XmlSerializer(typeof(T), "");
        return serializer.Deserialize(xmlReader) as T;
    }

    public static string ToXml<T>(this T t) where T : class
    {
        XElement element= ToXml(t, t.GetType());
        if (element != null)
            return element.ToString();
        return string.Empty;
    }
    public static XElement ToXml(object obj, Type type)
    {
        IList<XmlRootAttribute> xmlRoots = AttributeHelper.GetCustomAttributes<XmlRootAttribute>(type);
        if (xmlRoots == null || xmlRoots.Count < 1) return null;
        XmlRootAttribute xmlRoot = xmlRoots[0];
        string root = xmlRoot.ElementName;
        XNamespace ns = xmlRoot.Namespace;
        XDocument doc = new XDocument(new XElement(root));
        IList<PropertyInfo> xmlAttributes = AttributeHelper.GetPropertyWithCustomAttribute<XmlAttributeAttribute>(type);
        if (xmlAttributes != null && xmlAttributes.Count > 0)
        {
            foreach (PropertyInfo p in xmlAttributes)
            {
                XmlAttributeAttribute xmlattribute = AttributeHelper.GetPropertyCustomAttribute<XmlAttributeAttribute>(p);
                string attributeName = xmlattribute.AttributeName;
                object attributeValue = p.GetValue(obj, null);
                doc.Root.Add(new XAttribute(attributeName, attributeValue));
            }
        }
        IList<PropertyInfo> xmlElements = AttributeHelper.GetPropertyWithCustomAttribute<XmlElementAttribute>(type);
        if (xmlElements != null && xmlElements.Count > 0)
        {
            foreach (PropertyInfo p in xmlElements)
            {
                XmlElementAttribute xmlelement = AttributeHelper.GetPropertyCustomAttribute<XmlElementAttribute>(p);
                string elementName = xmlelement.ElementName;
                object elementValue  = p.GetValue(obj, null);;
                Type t = xmlelement.Type;
                if (t!=null && !types.Contains(t))
                    elementValue = ToXml(elementValue, t);
                doc.Root.Add(new XElement(elementName,elementValue));
            }
        }
        IList<PropertyInfo> xmlarrays = AttributeHelper.GetPropertyWithCustomAttribute<XmlArrayAttribute>(type);
        if (xmlarrays != null && xmlarrays.Count > 0)
        {
            foreach (PropertyInfo p in xmlarrays)
            {
                XmlArrayAttribute xmlarray = AttributeHelper.GetPropertyCustomAttribute<XmlArrayAttribute>(p);
                string array = xmlarray.ElementName;
                XElement element = new XElement(array);
                XmlArrayItemAttribute xmlArrayItem = AttributeHelper.GetPropertyCustomAttribute<XmlArrayItemAttribute>(p);
                string itemName = xmlArrayItem.ElementName;
                Type subtype = xmlArrayItem.Type;
                object o = p.GetValue(obj, null);
                IList c = (IList)o;
                for (int i = 0; i < c.Count; i++)
                {
                    XElement itemvalue = ToXml(c[i], subtype);
                    element.Add(new XElement(itemvalue));
                }

                doc.Root.Add(element);
            }
        }
        return doc.Root;
    }
}